/*
C++ 动态内存
了解动态内存在 C++ 中是如何工作的是成为一名合格的 C++ 程序员必不可少的。C++ 程序中的内存分为两个部分：

栈：在函数内部声明的所有变量都将占用栈内存。
堆：这是程序中未使用的内存，在程序运行时可用于动态分配内存。
很多时候，您无法提前预知需要多少内存来存储某个定义变量中的特定信息，所需内存的大小需要在运行时才能确定。

在 C++ 中，您可以使用特殊的运算符为给定类型的变量在运行时分配堆内的内存，这会返回所分配的空间地址。这种运算符即 new 运算符。

如果您不再需要动态分配的内存空间，可以使用 delete 运算符，删除之前由 new 运算符分配的内存。
*/
#include<iostream>
using namespace std;


class Box
{
   public:
      Box() { 
         cout << "调用构造函数！" <<endl; 
      }
      ~Box() { 
         cout << "调用析构函数！" <<endl; 
      }
};

int main() {
    double* pvalue = NULL; // 初始化为 null 的指针
    pvalue = new double;     // 为变量请求内存

    *pvalue = 25666.99;     // 在分配的地址存储值
    cout << "value of pvalue :" << *pvalue << endl;

    delete pvalue;                // 释放内存


    // 数组的动态内存分配
    char* pchar = NULL;
    pchar = new char[20];

    // 一维数组
    int *array = new int[12];
    delete []array;

    /*二维数组*/
    // int **p;
    // int i,j;
    // //开始分配4行8列的二维数据   
    // p = new int *[4];
    // for(i=0;i<4;i++){
    //     p[i]=new int [8];
    // }
 
    // for(i=0; i<4; i++){
    //     for(j=0; j<8; j++){
    //         p[i][j] = j*i;
    //     }
    // }   
    // //打印数据   
    // for(i=0; i<4; i++){
    //     for(j=0; j<8; j++)     
    //     {   
    //         if(j==0) cout<<endl;   
    //         cout<<p[i][j]<<"\t";   
    //     }
    // }   
    // //开始释放申请的堆   
    // for(i=0; i<4; i++){
    //     delete [] p[i];   
    // }
    // delete [] p;   

    /* 三维数组测试实例 */
    int i,j,k;   // p[2][3][4]
    
    int ***p;
    p = new int **[2]; 
    for(i=0; i<2; i++) 
    { 
        p[i]=new int *[3]; 
        for(j=0; j<3; j++) 
            p[i][j]=new int[4]; 
    }
    
    //输出 p[i][j][k] 三维数据
    for(i=0; i<2; i++)   
    {
        for(j=0; j<3; j++)   
        { 
            for(k=0;k<4;k++)
            { 
                p[i][j][k]=i+j+k;
                cout<<p[i][j][k]<<" ";
            }
            cout<<endl;
        }
        cout<<endl;
    }
    
    // 释放内存
    for(i=0; i<2; i++) 
    {
        for(j=0; j<3; j++) 
        {   
            delete [] p[i][j];   
        }   
    }       
    for(i=0; i<2; i++)   
    {       
        delete [] p[i];   
    }   
    delete [] p;  


    /*对象的动态内存分配*/
    // 对象与简单的数据类型没有什么不同。例如，请看下面的代码，我们将使用一个对象数组来理清这一概念：
    // 如果要为一个包含四个 Box 对象的数组分配内存，构造函数将被调用 4 次，同样地，当删除这些对象时，析构函数也将被调用相同的次数（4次）。
    Box* BArray = new Box[4];

    delete [] BArray; //删除数组

    return 0;
}